Міністерство освіти і науки України
Національний університет „Львівська політехніка”
Кафедра електронних
обчислювальних машин
Звіт
про виконання лабораторної роботи № 5
з курсу „ Моделювання ”
Тема:
Аналіз генераторів випадкових чисел.
Мета: Проаналізувати програмні генератори псевдовипадкових чисел
Теоретичні відомості:
Традиційно програмне забезпечення використовує програмні генератори псевдовипадкових чисел. Принципова відмінність даних генераторів від апаратних полягає в тому, що такі генератори кожного разу генерують ідентичну послідовність. Використання програмних генераторів спричинило багато неправильних результатів в низці наукових робіт [1]. До недоліків таких генераторів слід віднести достатньо невеликий період повторення псевдовипадкової послідовності, наявність низькочастотних кореляцій у генерованій послідовності. Розглянемо декілька підходів до розробки таких генераторів.
Використання рекурентних співвідношень вигляду:
або
де a, b, с, m – деякі цілі числа. Вибравши довільним чином деякі початкові значення для X, знаходимо кожне наступне число за співвідношеннями або . У випадку використання конгруенції всі генеровані числа належать до інтервалу . Саме такі співвідношення використовуються для реалізації функції rand() – стандартної функції бібліотеки мови С. Такі програмні генератори випадкових чисел мають низку недоліків.
Вони формують випадкові числа таким чином, що лише їх молодші біти є більш-менш випадковими. Тому при генеруванні випадкових чисел в інтервалі в жодному разі не можна використовувати співвідношення типу
,
оскільки генеровані таким чином випадкові числа характеризуватимуться іншими статистичними характеристиками. В даному випадку необхідно використовувати лише лінійне перетворення, наприклад:
Генератори випадкових чисел, побудовані на основі вищезгаданих співвідношень, характеризуються тим, що існують кореляції між згенерованими ними послідовностями. Зокрема, коли згенеровані таким чином послідовності k випадкових чисел відобразити у k-вимірному просторі, то відповідні точки не заповнюють весь простір, а лежатимуть на (k-1) вимірних площинах, причому таких площин буде не більше, ніж . Якщо крім того, коефіцієнти генератора ще й неправильно вибрано, то таких площин буде набагато менше, ніж [1].
Виконання роботи:
#include <dos.h>
#include <math.h>
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <graphics.h>
#define ESC 0x1b
int GraphDriver;
int GraphMode;
int MaxX, MaxY;
int ErrorCode;
double buff1[100];
unsigned int buff2[100];
unsigned int buff3[100];
unsigned int buff4[100];
int kilk=0;
FILE * fptr;
void Initialize(void);
void DrawGraphInt(char*, char*, int, unsigned int*);
void DrawGraphDoubl(char*, char*, int, double*);
void Pause(void);
void MainWindow(char *header);
void StatusLine(char *msg);
void DrawBorder(void);
void changetextstyle(int font, int direction, int charsize);
int main (void) {
clrscr ();
if((fptr=fopen("c:\\rezult_lab5.txt", "w"))==NULL)
{ printf("\nNe mozhu vidkryty fajl");
exit(1); }
buff1[0]=1;
int a=0, b=0, i=0, m=0;
printf ("----------Metod N1 (Xi+1=aXi+bint(aXi/b)) --------\n");
fprintf (fptr,"----------Metod N1 (Xi+1=aXi+bint(aXi/b)) --------\n");
printf ("Vvedit pochatkovi znachennya:\n");
printf ("a="); scanf ("%d", &a);
printf ("b="); scanf ("%d", &b);
printf ("kilkist="); scanf ("%d", &kilk);
for (i=0; i<kilk; i++)
{ buff1[i+1]=a*buff1[i]+b*(a*buff1[i]/b);
fprintf (fptr, "%.1f ", buff1[i]); }
fprintf (fptr, "\n");
//Metod 1
Initialize();
DrawGraphDoubl("Lab5 / First method demonstration", "Xi+1=aXi+bint(aXi/b)", kilk, buff1[0]);
printf ("---------- Metod N2 (Xj+1=(a*Xj) mod m) --------\n");
fprintf (fptr, "---------- Metod N2 (Xj+1=(a*Xj) mod m) --------\n");
printf...